package com.yangyang.lamviarm.server;

import java.awt.event.ActionEvent;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Random;

import com.yangyang.lamviarm.client.JClient;
import com.yangyang.lamviarm.client.LAMVaiRL;
import com.yangyang.lamviarm.entity.JActionModelDef;
import com.yangyang.lamviarm.server.javacc.JServerParser;
import com.yangyang.lamviarm.util.ClientActionEvent;
import com.yangyang.lamviarm.util.ClientActionListener;
import com.yangyang.lamviarm.util.ClientTerminateEvent;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * JServer.java
 *
 * Created on 2011-11-6, 19:34:56
 */
/**
 * 
 * @author Administrator
 */
public class JServer extends javax.swing.JFrame implements ClientActionListener {

	/** Creates new form JServer */
	public JServer() {
		initComponents();
	}

	/**
	 * This method is called from within the constructor to initialize the form.
	 * WARNING: Do NOT modify this code. The content of this method is always
	 * regenerated by the Form Editor.
	 */
	private void initComponents() {

		jScrollPane1 = new javax.swing.JScrollPane();
		txtServerStatus = new javax.swing.JTextArea();
		jPanel1 = new javax.swing.JPanel();
		txtPort = new javax.swing.JTextField();
		jLabel1 = new javax.swing.JLabel();
		btnStart = new javax.swing.JButton();
		btnExit = new javax.swing.JButton();
		jScrollPane2 = new javax.swing.JScrollPane();
		txtActionHistory = new javax.swing.JTextArea();

		setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
		setBackground(new java.awt.Color(204, 255, 204));

		txtServerStatus.setColumns(20);
		txtServerStatus.setEditable(false);
		txtServerStatus.setRows(5);
		jScrollPane1.setViewportView(txtServerStatus);

		txtPort.setText("10086");

		jLabel1.setText("Listen Port:");

		btnStart.setText("Start");
		btnStart.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				btnStartActionPerformed(evt);
			}
		});

		btnExit.setText("Exit");
		btnExit.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				btnExitActionPerformed(evt);
			}
		});

		txtActionHistory.setColumns(20);
		txtActionHistory.setEditable(false);
		txtActionHistory.setRows(5);
		jScrollPane2.setViewportView(txtActionHistory);

		javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(
				jPanel1);
		jPanel1.setLayout(jPanel1Layout);
		jPanel1Layout
				.setHorizontalGroup(jPanel1Layout
						.createParallelGroup(
								javax.swing.GroupLayout.Alignment.LEADING)
						.addGroup(
								jPanel1Layout
										.createSequentialGroup()
										.addGap(36, 36, 36)
										.addComponent(btnStart)
										.addPreferredGap(
												javax.swing.LayoutStyle.ComponentPlacement.RELATED,
												42, Short.MAX_VALUE)
										.addComponent(btnExit)
										.addGap(42, 42, 42))
						.addGroup(
								javax.swing.GroupLayout.Alignment.TRAILING,
								jPanel1Layout
										.createSequentialGroup()
										.addContainerGap(110, Short.MAX_VALUE)
										.addComponent(jLabel1)
										.addPreferredGap(
												javax.swing.LayoutStyle.ComponentPlacement.RELATED)
										.addComponent(
												txtPort,
												javax.swing.GroupLayout.PREFERRED_SIZE,
												54,
												javax.swing.GroupLayout.PREFERRED_SIZE))
						.addComponent(jScrollPane2,
								javax.swing.GroupLayout.DEFAULT_SIZE, 240,
								Short.MAX_VALUE));
		jPanel1Layout
				.setVerticalGroup(jPanel1Layout
						.createParallelGroup(
								javax.swing.GroupLayout.Alignment.LEADING)
						.addGroup(
								javax.swing.GroupLayout.Alignment.TRAILING,
								jPanel1Layout
										.createSequentialGroup()
										.addComponent(
												jScrollPane2,
												javax.swing.GroupLayout.DEFAULT_SIZE,
												294, Short.MAX_VALUE)
										.addGap(18, 18, 18)
										.addGroup(
												jPanel1Layout
														.createParallelGroup(
																javax.swing.GroupLayout.Alignment.BASELINE)
														.addComponent(btnStart)
														.addComponent(btnExit))
										.addPreferredGap(
												javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
										.addGroup(
												jPanel1Layout
														.createParallelGroup(
																javax.swing.GroupLayout.Alignment.BASELINE)
														.addComponent(jLabel1)
														.addComponent(
																txtPort,
																javax.swing.GroupLayout.PREFERRED_SIZE,
																javax.swing.GroupLayout.DEFAULT_SIZE,
																javax.swing.GroupLayout.PREFERRED_SIZE))
										.addGap(10, 10, 10)));

		javax.swing.GroupLayout layout = new javax.swing.GroupLayout(
				getContentPane());
		getContentPane().setLayout(layout);
		layout.setHorizontalGroup(layout
				.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
				.addGroup(
						javax.swing.GroupLayout.Alignment.TRAILING,
						layout.createSequentialGroup()
								.addComponent(jPanel1,
										javax.swing.GroupLayout.DEFAULT_SIZE,
										javax.swing.GroupLayout.DEFAULT_SIZE,
										Short.MAX_VALUE)
								.addPreferredGap(
										javax.swing.LayoutStyle.ComponentPlacement.RELATED)
								.addComponent(jScrollPane1,
										javax.swing.GroupLayout.PREFERRED_SIZE,
										332,
										javax.swing.GroupLayout.PREFERRED_SIZE)));
		layout.setVerticalGroup(layout
				.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
				.addComponent(jScrollPane1,
						javax.swing.GroupLayout.DEFAULT_SIZE, 376,
						Short.MAX_VALUE)
				.addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE,
						javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE));

		pack();
	}// </editor-fold>

	// Variables declaration - do not modify
	private javax.swing.JButton btnExit;
	private javax.swing.JButton btnStart;
	private javax.swing.JLabel jLabel1;
	private javax.swing.JPanel jPanel1;
	private javax.swing.JScrollPane jScrollPane1;
	private javax.swing.JScrollPane jScrollPane2;
	private javax.swing.JTextArea txtActionHistory;
	private javax.swing.JTextField txtPort;
	private javax.swing.JTextArea txtServerStatus;
	private String txtMask = "001100000";
	private LAMVaiRL client = null;
	public static PrintWriter writer = null;

	// End of variables declaration

	private void btnExitActionPerformed(java.awt.event.ActionEvent evt) {
		// TODO add your handling code here:
		System.exit(0);
	}

	boolean bInited = false;

	private void btnStartActionPerformed(java.awt.event.ActionEvent evt) {
		// TODO add your handling code here:
		this.btnStart.setEnabled(false);
		if (!bInited) {
			this.initServer();
			bInited = true;
		}
		new Thread() {
			@Override
			public void run() {
				startServer();
			}
		}.start();
	}

	private void initServer() {
		while (true) {
			this.txtActionHistory
					.append("reading from environment-description.txt\n");
			JServerParser parser = null;
			try {
				parser = new JServerParser(new BufferedReader(
						new InputStreamReader(new FileInputStream(
								"environment-description.txt"))));
			} catch (FileNotFoundException e1) {
				// TODO Auto-generated catch block
				this.txtActionHistory
						.append("file environment-description.txt not exist!\n");
				break;
			}
			try {
				int result = JServerParser.one_line();
				if (result == 0) {
					JSimulator.movePtr();
					this.txtServerStatus.append(JSimulator.simulator
							.toString(this.txtMask));
					this.txtActionHistory.append("file read succeed\n");
					break;
				}
			} catch (Exception e) {
				System.out.println("parser exception.");
				System.out.println(e.getMessage());
				System.out.println(e.getStackTrace());
				System.out.println(e);
				JServerParser.ReInit(System.in);
			} catch (Error e) {
				System.out.println("parser error.");
				System.out.println(e.getMessage());
				break;
			}
		}
	}

	private void startServer() {
		if (true) {
			if (client == null) {
				client = new LAMVaiRL();
				try {
					File file = new File(
							"c:\\yauta_data\\"
									+ new SimpleDateFormat("yyMMddhhmmss")
											.format(new Date()) + ".log");
					if (!file.exists())
						try {
							file.createNewFile();
						} catch (IOException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					this.writer = new PrintWriter(new OutputStreamWriter(
							new FileOutputStream(file)));
				} catch (FileNotFoundException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				client.setClientActionListener(this);
				writer.println("starttime : " + new Date().toLocaleString());
				client.run();
				writer.println("endtime : " + new Date().toLocaleString());
				this.btnStart.setEnabled(true);
			} else {
				if (!JSimulator.movePtr()) {
					this.btnStart.setEnabled(true);
					writer.flush();
					return;
				}
				// try {
				// this.writer.close();
				// File file = new File(
				// "c:\\yauta_data\\"
				// + new SimpleDateFormat("yyMMddhhmmss")
				// .format(new Date()) + ".log");
				// if (!file.exists())
				// try {
				// file.createNewFile();
				// } catch (IOException e) {
				// // TODO Auto-generated catch block
				// e.printStackTrace();
				// }
				// this.writer = new PrintWriter(new OutputStreamWriter(
				// new FileOutputStream(file)));
				// } catch (FileNotFoundException e) {
				// // TODO Auto-generated catch block
				// e.printStackTrace();
				// }
				this.txtServerStatus.append(JSimulator.simulator
						.toString(this.txtMask));
				client.readTrainData();
				client.clearActionModel();
				writer.println("starttime : " + new Date().toLocaleString());
				client.run();
				writer.println("endtime : " + new Date().toLocaleString());
				this.btnStart.setEnabled(true);
			}
			return;
		}
		int port = 10086;
		try {
			port = Integer.parseInt(this.txtPort.getText());
		} catch (Exception e) {
			this.txtActionHistory.append(e.getMessage() + "\n");
		}
		try {
			ServerSocket server = new ServerSocket(port);
			this.txtActionHistory.append("server started...\n");
			new Thread() {
				@Override
				public void run() {
					// TODO Auto-generated method stub
					try {
						Thread.sleep(5000);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					JClient.main(null);
				}

			}.start();
			Socket socket = server.accept();

			BufferedReader reader = new BufferedReader(new InputStreamReader(
					socket.getInputStream()));
			PrintWriter writer = new PrintWriter(socket.getOutputStream());

			while (true) {
				String line = reader.readLine();
				this.txtActionHistory.append(line + "\n");
				if (line.equals("exit") || line.equals("bye")) {
					writer.println(line);
					socket.close();
					break;
				}
				writer.println(line + ": result ="
						+ JSimulator.simulator.doAction(line));
				writer.flush();
				this.txtServerStatus.append(JSimulator.simulator
						.toString(txtMask));
			}
			server.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * @param args
	 *            the command line arguments
	 */
	public static void main(String args[]) {
		java.awt.EventQueue.invokeLater(new Runnable() {

			public void run() {
				new JServer().setVisible(true);
			}
		});
	}

	@Override
	public void actionPerformed(ActionEvent arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void OnClientActionDone(ClientActionEvent event) {
		// TODO Auto-generated method stub

		StringBuilder sb = new StringBuilder();
		sb.append("\n\n========" + new Date().toLocaleString() + "========\n");
		HashMap<String, List<JActionModelDef>> modelmap = event
				.getActionModel();
		if (modelmap == null || modelmap.size() == 0)
			return;
		for (String action : modelmap.keySet()) {
			sb.append("action:" + action + "\n");
			for (JActionModelDef model : modelmap.get(action)) {
				sb.append(model.toString() + "\t" + "qvalue:"
						+ model.getQValue() + "\told qvalue:"
						+ model.getOldQValue() + "\n");
			}
		}

		sb.append("\n========\n\n");

		if (new Random().nextInt(100) < 99) {
			// writer.println(event.getActionResult());
			// writer.println("action-model:" + sb);
			return;
		}
		this.txtActionHistory.append(sb.toString());
		this.txtServerStatus.append(event.getActionResult() + "\n");
	}

	@Override
	public void OnClientTeminated(ClientTerminateEvent event) {
		String sTerminatedMsg = "error\n";
		switch (event.getType()) {
		case 1:
			sTerminatedMsg = " the goal has reached \n";
			break;
		case 2:
			sTerminatedMsg = " client program has reached the max iterator number\n";
			break;
		case 3:
			sTerminatedMsg = " client reached a dead state,no action could be take\n";
			break;
		default:
			break;
		}
		this.txtServerStatus.append(sTerminatedMsg);
	}
}
